package com.hoku.gateway.filter;

import com.hoku.gateway.config.AccessFilterProperties;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

/**
 * zuul前置过滤器，过滤请求,这个filter有点多余，spring-security-oauth2本身已经提供了好多安全相关过滤器
 * @author ZHUFEIFEI
 */
@Slf4j
//@Component
//@EnableConfigurationProperties({AccessFilterProperties.class})
public class AccessFilter extends ZuulFilter {

    private static final String HEAD_AUTH_KEY = "Authorization";
    private static final String PARAM_TOKEN_KEY = "access_token";

    @Autowired
    private AccessFilterProperties accessFilterProperties;

    @Override
    public String filterType() {
        //前置过滤器
        return "pre";
    }

    @Override
    public int filterOrder() {
        //执行顺序，越小优先级越高
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        //过滤器是否执行
        return true;
    }

    @Override
    public Object run() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        this.debugTrace("{} {}",request.getMethod(),request.getRequestURL());
        //permit
        if (this.accessFilterProperties.getPermitUri().contains(request.getRequestURI())) {
            this.debugTrace("permit {} {}",request.getMethod(),request.getRequestURI());
            return null;
        }
        Object accessToken = Optional.ofNullable(request.getHeader(HEAD_AUTH_KEY))
                .orElseGet(()-> request.getParameter(PARAM_TOKEN_KEY));
        if (accessToken == null){
            log.warn("Authorization token is empty");
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.SC_FORBIDDEN);
            requestContext.setResponseBody("FORBIDDEN!");
            return null;
        }
        this.debugTrace("Authorization token : {}", accessToken);
        return null;
    }

    private void debugTrace(String format, Object ...o) {
        if (log.isDebugEnabled()) {
            log.debug(format, o);
        }
    }
}
